package net.qiqbframework.persisthanding;

import net.qiqbframework.common.Registration;
import net.qiqbframework.messaging.annotation.*;
import net.qiqbframework.modelling.domain.AggregateModelFactory;

import java.util.*;
import java.util.stream.Collectors;


public class AnnotationPersistHandlerAdapter<T> implements PersistMessageHandler {

    /**
     * 被 @PersistHandler 修饰的对象
     */
    private final T target;

    private final AnnotatedHandlerInspector<T> handlerInspector;


    @SuppressWarnings("unchecked")
    public AnnotationPersistHandlerAdapter(T target, HandlerParameterResolverFactory parameterResolverFactory,
                                           HandlerAttributesPostProcessor handlerAttributesPostProcessor,
                                           MessageHandlingMemberFactory handlerDefinition,
                                           AggregateModelFactory aggregateModelFactory) {
        this.target = target;
        this.handlerInspector = AnnotatedHandlerInspector.inspectType((Class<T>) target.getClass(), parameterResolverFactory, handlerAttributesPostProcessor, handlerDefinition);


    }


    public Registration subscribe(AggregatePersistBus persistBus) {

        Collection<Registration> subscriptions =
                supportedAggregateNames().stream()
                        .map(supportedCommand -> persistBus.subscribe(supportedCommand, this))
                        .collect(Collectors.toCollection(ArrayDeque::new));

        return () -> subscriptions.stream().map(Registration::cancel).reduce(Boolean::logicalOr).orElse(false);

    }


    @Override
    public Object handle(PersistMessage<?> persistMessage) throws Exception {

        final List<MessageExecutableHandler> matchedMessageHandlingMember = handlerInspector.getHandlers(target.getClass())
                .filter(ch -> ch.canHandle(persistMessage))
                .toList();

        for (MessageExecutableHandler handlingMember : matchedMessageHandlingMember) {
            handlerInspector.chainedInterceptor(target.getClass()).handle(persistMessage, target, handlingMember);
        }
        return null;


    }

    private Set<String> supportedAggregateNames() {
        return handlerInspector.getAllHandlers()
                .values()
                .stream()
                .flatMap(Collection::stream)
                .map(ch -> ch.unwrap(PersistExecutableHandler.class).orElse(null))
                .filter(Objects::nonNull)
                .map(PersistExecutableHandler::aggregateName)
                .collect(Collectors.toSet());
    }

}
